浅谈 stable diffusion (三) 本系列的第三篇,如果你看过前俩篇,想必已经对stable diffuison原理和优势与劣势甚至未来的发展方向有了一定了解。 stable diffuison发展至今,商业(实用)属性已经相当高了,所以我们对stable diffusion剩下的…

本系列的第三篇,如果你看过前俩篇,想必已经对 stable diffuison 原理和优势与劣势甚至未来的发展方向有了一定了解。

stable diffuison 发展至今,商业(实用)属性已经相当高了,所以我们对 stable diffusion 剩下的细枝末节就从实际操作的角度讲起。

那么便从 stable diffusion webUI 讲起......

如果你不想了解任何和原理有关的东西,你甚至能把这篇文章当做新手教程,hhh~

Stable Diffusion web UI

A browser interface based on Gradio library for Stable Diffusion.

整体介绍

webui 是基于 gradio 库搭建的图形界面,可以实现 stable diffusion 原始的 txt2img 和 img2img 模式,并提供了一键安装并运行的脚本。此外,webui 还集成了许多二次开发功能,如 outpainting、inpainting、color sketch 等。它还提供了 X/Y/Z 图等脚本生成方式以及文本反转、超网络等图形界面训练按钮,以及一系列 Extras 方法的快捷使用。

虽然 webui 自称为 stable diffusion 的 web 图形界面,但实际上它是 AI 图像生成的综合工具。由于基于 gradio 的优势,它在搭建、扩展、多平台适配上都非常方便和实用。然而,受限于 gradio 和图形界面,一些精细的调整或者对生成流程的微调无法进行精细操作。虽然其中一些流程可以通过添加插件弥补,但仍有一些限制。

总的来说,stable diffusion web ui 是初次接触扩散模型甚至是生成模型的新手最适合的图形化操作界面。接下来,我将按照 webui 的界面一一分析其中的原理、使用方法、效果和影响。此外,还可以通过 webui 进行许多扩展和调整,使其更适合个人的需求和喜好。

webui 原版样式

Stable Diffusion checkpoint

位置在 webui 的右上角,也是最重要的选项,可以在此处选择你的 stable diffusion 模型。

checkpoint(权重点),意味着里面存放着模型的权重参数,checkpoint 文件本质是一个变量名 - 变量值的词典。

一些疑问的解答

是否选择带 ema 的版本

如果你在很早期就亲自部署 webUI 或者经历或 novelai 的 leak 模型,你通常会有疑问,我究竟该选用 animefull-latest 的 7G 版本还是 final-pruned 的 4G 版本。

4G 版本其实是 7G 版本的修剪版本,因为 novelai 在训练模型时使用了 ema 算法,试图提升模型最终生成的效果。

Ema 是一种算法,可以近似获得近 n 步权重的平均值。该算法基于一个假设,即在训练的最后阶段,权重会在实际的最优点附近波动。通过取最近 n 步权重的平均值,可以使得模型更稳定。

早期一些人有一个误区,认为修剪版本的模型删除了 ema 部分的权重,事实上恰恰相反,修剪模型删除了所有非 ema 的权重。而且由于启用 ema 后运行非修剪版本时等同于运行修剪模型,所以单纯从生成的角度来说,俩个模型的效果是一致的。

泄露文件里模型对应的 config 文件可以控制是否启用 ema

但是由于修剪版本的模型删除了非 ema 的权重,所以相比真实训练出的权重有失真,所以笔者认为如果你有数据洁癖或者坚持某种心理玄学在进行基于 novelai leak 模型进行二次训练时最好选择非修剪版本,但是笔者认为 ema 对于扩散模型来说不是很重要(相对于 GAN)。

具体来讲就是如果你想要继续训练,且拥有足够的计算机资源,就选择非修剪版本,因为既有 ema 权重,也有标准权重,训练时根据标准权重进行训练,在模型的 config 文件应该关闭 ema,在模型训练的脚本里应该开启 ema 算法,具体因脚本而异。
如果你想要进行使用,如果你选择的是非修剪版本且你认为 ema 对你有帮助,就在 config 文件中开启 ema,这样你的模型就应用了 ema。
修剪版本利用 ema 权重替换了标准权重,标准权重实际是经过 ema 算法后的权重,所以修剪版本通常被称为不带 ema。

所以答案很明显:

该选择 float16 还是 float32 版本

float16 和 float32 代表模型的权重保存的精度,float32 的长度是 float16 近一倍,与之带来的是 float32 版本的模型文件通常要大很多。通常而言我们将 float32 称为单精度,float16 称为半精度,float64 称为双精度。

神经网络训练对精度降低的容忍度非常高

在实际生成的过程中,精度带来的影响微乎其微,笔者这里推荐是使用 float16 的版本作为生成使用,节省内存和显存。

在实际训练的过程中,对于 stable diffusion 来说精度带来的影响也是较小,当然实际训练过程中通常采用混合精度训练,最后使用 float32 的形式保存,财大气粗直接以 float32 的形式训练也行。

至于 float16 和 float32 版本对你来说谁更快,你应该参照你的 N 卡参数来判断。

说的就是你,T4

是否应该加载 vae

模型文件即 checkpoint 是已经包含了 vae(用于从隐空间解码,详见第一篇)相关参数,但是 stable diffusion 官方和 novelai 泄露出来的文件都有额外的 vae,因为这些 vae 针对面部或者其他一些细节做了改良,所以加载 vae 文件实际是替换了模型文件中原有的与 vae 相关的参数。

当然由此引发的问题就是,如果你的模型原本的效果就很好,盲目加载 vae 可能弄巧成拙。或者如果你的模型文件已经注入过 vae,你再加载同样的 vae 只是浪费时间。

我一直认为 vae 文件应该被称为 vad(decoder,解码器)......
就训练来说我们主要用的 vae 中编码器(encoder)用于将图像转到隐空间,就生成来说我们主要用的 vae 中解码器(decoder)用于从隐空间解码

这里额外提一下设置,在 setting 里填入 sd_vae,会在 webui 上方显示你价值的 vae 模型

如图

模型文件的后缀

模型文件的后缀为.ckpt或者.safetensors

.ckpt 文件是用 pickle 序列化的,这意味着它们可能包含恶意代码,如果你不信任模型来源,加载 .ckpt 文件可能会危及你的安全。

.safetensors 文件是用 numpy 保存的,这意味着它们只包含张量数据,没有任何代码,加载 .safetensors 文件更安全和快速。

其中风险利弊自行衡量

模型文件后面 [] 内的 hash 值

hash 值通常来标注模型的唯一性,但是由于位数较短存在撞车可能,不是很实用。

stable diffusion 算 hash 的算法经过变动,最近算 16 位 hash 的算法更改为了 sha256,但是由于位数较低,撞车概率还是很高,如果遇到了相同 hash 的模型想要判断是否相同还请自行算更多位数的 hash 值来进行比较。

文生图 / txt2img

Prompt/Negative prompt

正向和反向提示词,用于文本条件生成。

正向提示词用于引导你想生成什么,反向提示词用于反向引导你不想生成的东西。

如果你阅读过前俩篇,你可能疑惑我之前没有提到过 Negative prompt,那么我就在这里进行一并讲解

第一篇我们讲到在包含文本条件生成时,文本提示词被转换成语义向量,而语义向量则被送入 U-Net 进行噪声预测。在 stable diffusion 中实际上有俩组语义向量,一种用于正向提示,一组用于反向提示。那么这些提示究竟是怎么工作的呢?

我们先观看只有正向提示时的工作流程:

在 stable diffusion 进行采样时,算法首先使用由正向提示引导的条件采样对原始的图像(噪声)进行降噪,然后采样器再使用无条件采样再对同一图像(噪声)进行一些去噪(该过程不受文本提示影响),但是就算是无条件采样同样会是朝着一个具体的画面扩散,就像下图的篮球或酒杯(可以是任何东西,不过我们拿酒杯和篮球举例)。

在这样的一个过程中,你实际得到的图像是最开始的有条件采样得到的图像减去无条件采样的图像后的差异,这个过程重复数次最终获得你的成品图。过程如下图:

Without negative prompt, a diffusion step is a step towards the prompt and away from random images.

那么如果我们携带反向提示会发生什么(该过程将胡子作为反向提示词)?

反向提示实际上是劫持了无条件采样,我们的无条件采样过程变成了使用反向提示进行采样,那我们的图像(噪声)就向着反向提示扩散,然后我们用正向提示得到的图减去反向提示得到的图,然后如此重复,不就减少了负面提示词代表的内容出现的可能吗。过程如下图

When using negative prompt, a diffusion step is a step towards the positive prompt and away from the negative prompt.

以上的例子只是为了帮助理解而以图像的形式进行说明,实际 stable diffusion 的生成过程是在隐空间(latent space)进行,所以本例子并非真实的生成流程,但是本质是一致的

程序正义党不要喷我,嘤嘤嘤~

prompt 的语法

如果你看到不同版本的说法,当你使用 webui 进行生成时请以笔者为准(从源码中整理出来,希望有人打脸)。

注意:通常有人认为|也是一种特殊语法,但是很遗憾 webUI 里是没有|这种语法的(我没有从代码中找到),这个语法仅用于 novelai,用于混合不同元素,不过 webui 也提供了其他语法来变相实现这一过程(AND)。

增强 / 减弱(emphasized)

通常有如下语法来影响一个提示词的影响程度:

() 强度变为1.1[] 强度变为0.9倍
(keyword:XX) 强度变为XX倍
以下俩个例子都是强度变为1.1倍
(keyword)
(keyword:1.1)
以下俩个例子都是强度变为0.9[keyword]
(keyword:0.9)
可以使用多个()或[]来影响强度
例如,多个使用时就是简单的相乘
(keyword): 1.1倍
((keyword)): 1.21倍
(((keyword))): 1.33[keyword]: 0.9[[keyword]]: 0.81[[[keyword]]]: 0.73倍
那么假如我是大聪明,我偏要用以下写法会发生什么
[keyword:1.9]
可莉也不知道哦~.jpg

影响程度的范围在 0.1 到 100 之间

这种增强 / 减弱是如何实现的呢?你如果看过第一章,我们的单词其实是转化为了语义向量(768 维空间中),那么缩放这个向量就能使得相关概念变强或减弱

注意当你不想使用 emphasized 而是想用()作为字符串时,你可以这样输入:

\(word\)

这里有个有关 setting 是默认被打开的

渐变 / 调整作用时机(scheduled)

通常有如下语法来进行渐变 (一定程度上可以理解为混合) 俩个提示词:

[keyword1 : keyword2: amount]
可以理解为[from:to:when]

amount的范围是 0 到 1,代表作用时机,如何实现? 举个例子:如果你的amount为 0.75,而采样步骤是 40 步,那么会有 40*0.75=30 步的过程,提示词为keyword1,剩下 10 步提示词为keyword2 所以如果你试图均匀 “混合”,最好将amount调为 0.5 左右

示例如下图:

注意当amount的大小 > 1 时,amount指的就是特定步数切换

a [fantasy:cyberpunk:16] landscape
这个例子在第16步后变为 a cyberpunk landscape

所以由此诞生了一个非常有用的技巧,如下

我们将(ear:1.9)作为正向提示词
然后我们将这个放入反向提示词
[the: (ear:1.9): 0.5]
第一个关键词为一个毫无意义的词,第二个关键词为(ear:1.9)代表我们想要生成耳朵
假如你的采样步骤为20步,则前10步会减少一个毫无意义的东西出现的概率,后10则会执行(ear:1.9)来减少耳朵出现的概率

我们就得到了一张类似上图一般头发遮住耳朵的图

究其原因是在扩散的过程中最开始的步骤往往更重要,后面的步骤则是对细节进行了更精细的调整

通过这个技巧我们可以将一些提示词只作用于后面的步骤或者只作用于前面的步骤

值得注意的是这个语法有简写方式如下:

[to:when] - 在某步后添加某个词条(to)
[from::when] - 在某步前使用某个词条(from

理解了,让我们来看个复杂例子

fantasy landscape with a [mountain:lake:0.25] and [an oak:a christmas tree:0.75][ in foreground::0.6][ in background:0.25] [shoddy:masterful:0.5] 
以上例子采用100步采样
下方为某步数后我们实际的prompt
最开始, fantasy landscape with a mountain and an oak in foreground shoddy
25步后, fantasy landscape with a lake and an oak in foreground in background shoddy
50步后, fantasy landscape with a lake and an oak in foreground in background masterful
60步后, fantasy landscape with a lake and an oak in background masterful
75步后, fantasy landscape with a lake and a christmas tree in background masterful

交替(alternate)

一个很有意思的语法,也可以用来混合一些提示,示例如下:

[keyword1|keyword2] keyword1和keyword2在采样时被交替使用
[A|B|C|D] A,B,C,D按顺序被交替使用
比如接下来的例子
[red hair|yellow hair], long hair, 1girl

在使用 DPM++ 2M Karras 采样时

第 10 步,头发偏向黄色(使用不同种子,多次生成)

第 11 步,头发偏向红色(使用不同种子,多次生成)

第 13 步,头发偏向黄色(使用不同种子,多次生成)

如上文所说,扩散的过程中最开始的步骤往往更重要,所以在逐渐收敛的后,你的交替词往往也会效果减弱,最终发色也会其中偏向一种,不会在下一步产生大变。

组合 / 混合(composable)

组合的关键词是AND,注意要大写(我们实际短语的 and 应该是小写,笔者认为这样做是为了将 prompt 语法和实际自然语言进行区别),这个AND关键词允许组合(混合)多个提示。

对 novelai 的|的 webui 版实现
a cat AND a dog

效果如下图

值得注意的是,你可以像 novelai 中一般可以为每个词提供权重,默认为 1,比如:

a cat :1.2 AND a dog AND a penguin :2.2

如果你的某个提示词权重低于 0.1,那么该提示词对应的要素就很难产生影响

断开 / 打断(BREAK)

断开的关键词是BREAK, 注意要大写。这个关键词会打断上下文的联系,强行进行再次分组(详见下文)。

词汇的具体解析

stable diffusion 使用 Clip 作为文本的编码器(详见第一篇),Clip 的标记器在标记之前将所有单词小写。

得益于 Clip 的强大,你可以在提示词里使用自然语言(主要是英语,看模型训练时的情况),也可以使用类标记语言。

提示词中开头和结尾的额外空格会被直接丢弃,词与词之间的多余空格也会被丢弃。

支持颜文字 和 emoji ,Unicode 字符(如日语字符)。

拼写错误或罕见词

提示单词可以由一个或多个符号组成,常用词通常被解析为具有共同含义或少量含义的单个标记。而拼写错误和不常见的单词被解析为多个可以被识别的标记,示例如下:

bank,bankk会被识别为bank,而bonk不会被识别为bank
_ 通常不会被转换成空格

笔者认为这个拼写错误被识别是很大原因因为 Clip 在训练过程中,人类也有拼写错误然后联系上下文同样能产生识别这个词的效果。

人总会犯错,机械飞升吧~

而对于罕见词,他们的信息量太低会被理解为其他的词语,这也解释了颜文字和 emoji 的作用性相比自然语言更强,因为颜文字和 emoji 对特定的含义信息是强绑定的关系而且字符数短,而自然语言通常会有歧义。

笔者此处是从信息论的角度来看,是不准确的描述

词汇顺序 / 数量 / 位置影响

这是个好问题,以笔者对 Clip 浅薄的理解,词汇们被转化成语义向量输入到 U-Net 时利用了 attention 机制(详见第一篇),而语义向量将会添加到一个位置标记上( a position embedding token),早期的标记具有更一致的位置,因此神经网络更容易预测它们的相关性。而且由于 attention 机制的特殊性,每次训练时,开始的标记和结束的标记总会被注意到(attention)。而且由于标记越多,单个标记被被注意到的概率越低。

基于以上特性,笔者认为有以下几点需要注意:

关于数量,你可能已经注意到了,当你写 prompt 时会有数量限制

但是在 webui 中,你是可以写 75 个词汇以上的提示的。webui 会自动通过对提示词进行分组。当提示超过 75 个 token(可以理解 token 代表你的提示词),提交多组 75 个 token。单个token只具有同一组中其他内容的上下文。

每一组都会被补充至 (1,77,768) 的张量,然后进行合并,比如俩组就会合并为 (1,154,768) 的张量,然后被送入 U-Net。

值得注意的是

emoji 和颜文字

对 emoji 的表现良好,对热门的颜文字(欧美环境)表现良好,而且作用力很强

[red hair|yellow hair], long hair, 1girl,✌️

采样方法 / Sampling method

如果你阅读过第一篇或第二篇,想必对采样方法已经有了自己的理解,我们可简单的将采样过程理解为一步一步将原有图片(噪声)去噪得到我们想要图片的过程。

webui 中集成了很多不同的采样方法,这里结合设置中提供的选项,简单粗略的介绍下它们(不含数学,放心食用)。

Euler

基于 Karras 论文,在 K-diffusion 实现
20-30steps 就能生成效果不错的图片
采样器设置页面中的 sigma noise,sigma tmin 和 sigma churn 会影响

Euler a

使用了祖先采样(Ancestral sampling)的 Euler 方法
受采样器设置中的 eta 参数影响

LMS

线性多步调度器(Linear multistep scheduler)源于 K-diffusion

heun

基于 Karras 论文,在 K-diffusion 实现
受采样器设置页面中的 sigma 参数影响

DPM2

Katherine Crowson 在 K-diffusion 实现
受采样器设置页面中的 sigma 参数影响

DPM2 a

使用了祖先采样(Ancestral sampling)的 DPM2 方法
受采样器设置中的 ETA 参数影响

DPM++ 2S a

基于 Cheng Lu 等人的论文,在 K-diffusion 实现的 2 阶单步并使用了祖先采样(Ancestral sampling)的方法
受采样器设置中的 eta 参数影响
Cheng Lu 的 github](https://github.com/LuChengTHU/dpm-solver) 中也提供已经实现的代码,并且可以自定义,1、2、3 阶,和单步多步的选择
webui 使用的是 K-diffusion 中已经固定好的版本

DPM++ 2M

基于 Cheng Lu 等人的论文的论文,在 K-diffusion 实现的 2 阶多步采样方法
被社区玩家称为最强采样器,速度和质量平衡优秀
比上方版本更优秀也更复杂

DPM++ SDE

基于 Cheng Lu 等人的论文的,DPM++ 的 SDE 版本(随机微分方程),DPM++ 原本是 ODE(常微分方程)
在 K-diffusion 实现的版本中调用了祖先采样(Ancestral sampling)方法,所以受采样器设置中的 ETA 参数影响

DPM fast

基于 Cheng Lu 等人的论文,在 K-diffusion 实现的固定步长采样方法,用于 steps 小于 20 的情况
受采样器设置中的 ETA 参数影响

DPM adaptive

基于 Cheng Lu 等人的论文,在 K-diffusion 实现的自适应步长采样方法
受采样器设置中的 ETA 参数影响

LMS Karras

基于 Karras 论文,运用了相关 Karras 的 noise schedule 的方法,可以算作是 LMS 使用 Karras noise schedule 的版本

DPM2 Karras

使用 Karras noise schedule 的版本

DPM2 a Karras

使用 Karras noise schedule 的版本

DPM++ 2S a Karras

使用 Karras noise schedule 的版本

DPM++ 2M Karras

使用 Karras noise schedule 的版本

DPM++ SDE Karras

使用 Karras noise schedule 的版本

DDIM

随 latent diffusion 的最初 repository 一起出现, 基于 Jiaming Song 等人的论文
目前最容易被当作对比对象的采样方法
在采样器设置界面有自己的 ETA

PLMS

元老级,随 latent diffusion 的最初 repository 一起出现

UniPC

目前最新采样器,基于 Wenliang Zhao 等人) 的论文
理论上目前最快采样器,10 步即可获得高质量结果

以上采样器,读者可以从字体大小中看出笔者的偏心,字体稍大的采样器在采样方法的发展史(虽然很短)中发挥了更大的作用,笔者也比较推荐用字体更大的那几种采样器(魔法师们开心就好,不要在意)。

俩个参数

eta 参数

eta (noise multiplier) for DDIM 只作用 DDIM,不为零时 DDIM 在推理时图像会一直改变,生成的图像不会最终收敛

换句话说,即使跑了数百步,图像依旧可能产生大变化。

eta (noise multiplier) for ancestral samplers 作用于名字后缀带 a 和 SDE 的所有采样器,不为零时生成的图像也不会收敛(而且同种种子同样参数也可能会不同

你可能注意到了上面很多款采样器提到了祖先采样(ancestral),而且它们中的大多数名称内含有a或者SDE

eta noise seed delta,在该值不为零时起到固定初始值的作用,这样你就可以使用相同值还原某些其它人使用了对应 eta 值的图片(通过相同的 seed)

相关设置:

对于魔法师而言,要注意 eta(前俩者)不要为 0,否则可能会 “失去” 多样性和创造性,要注意 eta(第三个)要和你准备复制的 “法术” 的 eta 相同,不然无法完美复制。

sigma 参数

sigma 包含:sigma churn,sigma tmin,sigma noise,仅对 euler, heun 和 dpm2 这三个采样器有效

sigma churn:决定 sigma noise 值如何被使用,如果 churn 值为 0,即使 noise 值不为 0,也没有任何效果。

sigma tmin:决定最小值范围的限制,可以为 0

sigma noise:噪声本身的数值大小(注意,churn>0 时,噪声值本身才有意义)

对于魔法师而言,sigma 值也与多样性和创造性有关。

采样步数 / Sampling steps

采样步骤与采样方法息息相关,每次采样相当于对原始图像(噪声)进行了一次去噪

最初的 DDPM 采样步数需要上千步才能获得高质量的图片,其消耗的算力和时间成本不可接受(隔壁 GAN 推理图片时间在 0.5 秒内)

在牺牲准确和多样性的情况下,我们选用了效率更高的采样方式 DDIM,获得高质量的图片只需要五十到上百步

后来如 DPM++ 2M 之类的采样算法更是将采样步骤缩进至 20 步,UniPC 更是只需要 10 步左右就能获取高质量的图片,与之带来的是采样的时间和算力消耗大幅下降,同样的时间内同样的设备能生成出的作品能够更多。

至于其中的牺牲,就笔者而言认为是微不足道的(无法诞生于世的东西是没有意义的)

对于魔法师来说,可能最好用的是 Euler a 或者 DDIM 或者 PM++ 2M,但是各种采样器生成出来的图片差距还是比较大的,请魔法师自行权衡。

注意一下,上文所讲的 eta 参数和 sigma 参数会影响不同步数下的多样性

宽 高 / Width Height

上面三个可选参数我们选择在后面再讲

非常明显,这俩按钮用来指定图片的宽和高

看到了这个按钮吗,这个按钮能轻松将宽和高进行数值交换

但是值得注意的是,stable diffusion 最开始是基于从 256X256 大小的数据集上训练出的 latent diffusion model 上用 512X512 的数据集继续训练而产生,2.0 后则使用 768X768 的图片在继续进行训练

所以根据原理,stable diffusion 生成 512X512 左右的图片效果更好,stable diffusion 在 2.0 版本后的模型至少将一侧设置为 768 像素产生的效果会更好

根据前俩篇文章我们知道,我们在生成时,先是产生了一个随机噪声,这个噪声在隐空间中反映为一个张量,这个张量受到我们想生成的图片分辨率大小影响,比如我们隐空间张量大小为 4X64X64 时对应着外面的 512X512 图像,隐空间张量大小为 4X96X96 时对应着外面的 768X512 图像。

根据笔者自己从零训练的 latent 模型来看,数据集采用 512X512 大小的图片而去生成 256X256 尺寸的图片时只会生成图片的部分,但是可能由于 stable diffusion 耗费巨资在训练时加入过不同分辨率的数据集,笔者所经历的现象将会减弱(大模型的黑盒)

但是就目前的 stable diffusion 来看,生成过大图片还是会出现问题,比如:

a girl,red hair

生成图片如下,产生了俩个女孩(笔者认为在生成时局部空间内产生收敛,导致最后的图片看着像是俩张图片拼接)

正确的生成图片大小策略

基于以上讨论,我们认为以下是生成图片大小是应选择的策略

CFG 指数 / CFG Scale

这是个很重要的概念,前俩篇没讲,我这里具体讲一下(偏直观,不含数学推理)。

如果你看过前俩篇,我们知道扩散模型的前向扩散和反向去噪都可以用随机微分方程来进行描述,对于反向去噪过程我们通过神经网络来拟合当前输入关于原数据分布的梯度(噪声预测过程)。问题是原有的噪声预测适用于随机(无条件)生成图像,单单有这个我们无法做到条件生成。

但是根据一些数学推论,我们可以推出利用分类器来指导条件生成。

对于一个先验分布,我们想要再次获得数据分布里在条件约束下的数据点时,我们实际只要在原来往数据方向的梯度方向上再额外添加一个分类器的梯度方向即可。

那么我们如何去构造一个分类器呢?

构造显式分类器存在许多问题。

首先,需要额外训练一个能够在噪声图像上进行分类判别的分类器,这需要耗费很多时间和精力。其次,该分类器的质量将决定按类别生成的效果。

实际上,将图像的判别梯度更新到分类器上是一种经典的图像界对分类模型进行对抗攻击的方法,然而,骗过一个并不健壮的分类器并不代表我们确实逼近了条件分布。

为了避免显式分类器的一些缺陷,我们推出了 classifier-free(无分类器),其核心是对无条件生成的网络以 omega+1 的强度进行有分类器引导的扩散生成等价于对有条件生成的网络以 omega 的强度进行有分类器引导,所以我们可以在 diffusion 里构造构建一个隐式的分类器梯度。使用隐式分类器引导的最终解析式要求我们只需要训练两个梯度预估模型,其中一个是无条件生成的梯度预估模型(例如常规的 DDPM),另一个是基于条件的梯度预估模型。

通过使用 classifier-free,一方面大大减轻了条件生成的训练代价(无需训练额外的分类器,只需要在训练时进行随机 drop out condition 来同时训练两个目标),另一方面这样的条件生成并不是以一个类似于对抗攻击的方式进行的,本质上是它是两个梯度的差值所形成的,避免了这种方式的缺点。

GAN 表示......

看到了这里,如果你想到了我们上文提到的 Prompt/Negative prompt 的作用方式,恭喜你,你想对了,Prompt/Negative prompt 处给的例子其实就是就是 classifier-free 过程造成的。

classifier-free guidance(无分类器引导生成)简称 CGF 堪称 stable diffusion 的奠基工作,以前说到跨模态我们通常只会想到 clip,对生成的图像和文本的距离做一个损失差值来引导图像生成(详见第一篇),现在我们有了无分类引导生成,让文生图更加高效和自然。

实际使用时的 CFG Scale

Classifier-free guidance scale(CGF 指数)用来调节文本提示对扩散过程的引导程度。

当数值为 0 时,图像生成是无条件的,数值较高时会向你的提示进行生成。

实际使用时,具体的 CGF 数值应当与你的模型息息相关,但是鉴于市面上很少有像笔者这样从零练了 latent diffusion model(至少需要一张 A100),我们使用 novelai 泄露模型时,通过实验获得的 CFG Scale 参数经验基本是通用的,以下可能是对你有用的经验之谈:

生成 / Gennerate

如果你有好好理解我前面所说的,就可以大胆按下这个按钮生成你想要的图像了

接下来我会讲解更加进阶的操作

面部修复 / Restore faces

我之所以说 webui 是 AI 图像生成的综合工具, 是因为它还集成了许多与 diffusion 关系不大的东西

比如我们现在讲的面部修复,面部修复是额外的模型,所以如果你初次使用可能会自动进行下载。

默认的面部修复模型是 CoderFormer,此外还有 GFPGAN,你可以在 setting 内进行更改。

下面的数值条可以控制 CoderFormer 的影响力度,为 0 时效果最强。

众所周知面部修复模型是用来修复面部的面部修复模型是用来修复面部的面部修复模型......

启用面部修复可能对你生成的画风和细节产生一些不可预知的影响,笔者对这个选项不是很感兴趣,魔法师请自行确认效果。

生成无缝贴图 / Tiling

这个功能可以说是设计师狂喜了,比如生成这样的图像,轻易突破想象极限(

高清修复 / Hires. fix

这个功能也是重量级了,尽管和 diffusion 模型的关系不大,但是根据上文,我们 stable diffusion 最好是生成 512X512 或者 768X768 附近大小的图片,但是显然这种像素级别对于现代人的 24K 钛晶眼来说不太够用,那么我们就可以通过高清修复(原理利用了超分辨率 / 图像增强)来达到我们的目的。

我们点击该选项后出现如下界面,按照惯例我们一个一个讲

图像放大器 / Upscaler

点开的列表是一系列放大算法,由于大部分和 stable diffusion 无关,所以我们只讲部分

首先要讲的是

Lanczos 插值和 Nearest 插值算法,这俩位是计算机图形学成果,是用于超分图像的传统算法,纯靠数学运算,充满了原始而自然的风味。

bicubic 插值算法也被称作双三次插值算法,如果从信号与系统的角度讲,bicubic 其作用原理接近一个低通滤波器,属于 sa 信号重建函数,是常见的视频图片质量增强算法。

而前缀有Latent的情况代表他们工作在隐空间(详见第一二篇)。

那么是什么现代的做法呢,现代的做法是追求算法和人工智能结合。

这里我简单介绍一下与人工智能有关的放大器的通用原理:

我们首先拿到高质量的图像数据,然后我们人为破坏将图片分辨率降低,然后尝试通过训练神经网络模型用来恢复原始图像。

笔者认为以信息论的角度讲,图像的高清修复就是要凭空增加信息,而一张图片单纯想要通过某种数学算法来增加信息是很难的。但是神经网络模型本身蕴含巨量信息,所以我们选择训练神经网络模型来进行对图片增加其信息的操作。

LDSR

中文名为潜在扩散超分辨率模型,放大器们中唯一和 diffusion 模型靠边的,它出现于 stable diffusion 的 v1.4 版本。

LDSR 虽然能提供不错的放大效果(写实类),但是非常缓慢,不是很推荐。

如果你读过前俩篇,我们就已经知道扩散模型的前向过程是对图像的破坏,而反向过程是对图像的复原,你是不是马上就联想到了上文我们提到的人工智能有关的放大器的通用原理。可以说扩散模型是天生适合干这件事的,但是基于 diffusion 的超分辨率相关工作还不是很成熟,目前存在一些缺点。

R-ESRGAN 4x+

中文名为真实 - 增强型超分辨率生成对抗网络(R-ESRGAN)模型,R-ESRGAN 4x + 是 ESRGAN 的增强版。

GAN 在图像超分辨率这个领域发展很早,所以目前效果出色,能保留精细的细节并产生清晰锐利的图像。

而 R-ESRGAN 4x 在恢复各种真实世界图像时有更强效果,能产生更平滑的图像。

R-ESRGAN 4x+ Anime6B

上面的模型在六十亿参数的动漫数据集上训练的结果,理论上相对上面能在二次元风格的图片上产生更优秀的效果。

以上俩个放大模型你可能需要前往设置进行添加

SwinIR_4x

基于 Jingyun Liang 等人的论文,看着挺不错,但是各方面性能打不过上面俩

放大步数 / Hires steps

整个 Hires. fix 过程你可以理解为我们在图像进行放大后,再基于该图像进行了二次生成

这个 Hires steps 就是我们二次生成时的步数,如果数值保持为 0,就代表和原有图像生成时的步数相同。

由于该步数对最终图像影响很大,所以生成图片时还请自行尝试对你模型和提示词和采样方法比较适合的步数。

如果你是个懒人直接置 0 即可

去噪强度 / Denoising strength

代表我们在进行 Hires 步数前,往隐空间(latent space)的图像信息添加的噪声强度。

这个选项对于latent系列的放大器值处于 0.5-0.8 时效果较好,较低时结果会非常模糊

也就是说如果你用 ESRGAN 之类的放大器就可以将本项置 0

此时就会直接放大图片,而不会对图像进行二次生成,比较省时

如果你在用 ESRGAN 之类的放大器时不将本项置 0,相当于做了一次图生图的流程

但是有些魔法师喜欢这样做,你怎么看呢

放大倍数 / Upscale by

通常你只需要注意一下这个,表示你最终图片的像素大小

放大至 / Resize width height to

如果启用这个,上面所说的放大倍数就会失效,但是这个更方便微调。

如果俩项都置 0,那么上面所说的放大倍数就会重新生效。

经验总结

图像生成种子 / Seed

这是个非常有用的功能,涉及到对图像的微调

Seed 影响你生成时潜在空间生成的随机图像(噪声),理论上,同样的 Seed 和同样的其他参数会同样的结果。

生成看似在玄学抽卡,实际每一步都有数学支撑(

注意 Seed 受到 eta noise seed delta 影响

在该值不为零时起到固定初始值的作用,这样你就可以使用相同值还原某些其它人使用了对应 eta 值的图片(通过相同的 seed)

注意使用了包含祖先采样(ancestral samplers)的采样器即使使用同样的 seed 仍然可能产生差别

Seed 值在为-1时代表随机生成一个 Seed

示例:

我们以 - 1 为 seed 生成一张图

下方出现的图片信息表示这张图的 seed 为 632817208

我们以 632817208 作为 seed 再生成一遍,便可以得到一样的图

为什么说它很有用呢?

因为你可以在这个 seed 的基础上采用不同 prompt 或者采样步数或者超分来得到你想要的差异化结果。

上图俩按钮,一个用于随机生成种子(骰子),一个用于获取上张图的种子(回收)

附加 / Extra

如果你点击了附加/Extra就会看到扩展栏

种子变异 / Variation seed

你可以填入你想使用的变异种子,具体规则和 seed 一致

变异强度 / Variation strength

变异种子和原种子的差异强度,为 0 时为原种子,为 1 时是新种子

这里有个技巧,首先我们 seed 设置为 1 进行生成

然后我们 seed 修改为 3,进行生成,发现姿势变化了

然后我们在种子变异栏里填上 1,变异强度设置为 1,便得到了和第一张一样的图

那我们把变异强度修改为 0.5 又会如何,得到了貌似是俩者之间的图

至少与两者有所关联

调整种子大小

这个功能挺有用,其原理与上文提到调整图片大小类似,将隐空间大小进行改变,但是我们生成的图片的尺寸没有变化。

通常,当改变分辨率时,图像会完全改变,即使保留了包括种子在内的所有其他参数。

但是通过调整种子大小,可以指定原始图像的分辨率(更正确的说法是隐空间的噪声信息对应的外面的图像的分辨率),而且模型很可能会产生与之非常相似的结果,即使在不同的分辨率下也是如此。

例子:

InfoImage
Seed resize not enabled
Seed resized from 512x512

批量生成

上面的按钮是生成次数,下面的按钮是每次数量

理论上讲,显存够的话每次数量(Batch size)越高总体生成越快,但是增加每次数量都会加大显存消耗

需要注意

通过批量生成 + 指定种子或种子变异可以在一个可控的范围内不断修改画面,方便使用者达到想要的效果。

脚本 / Script

webui 提供了一系列脚本来方便生成,该功能非常好用,建议魔法师一定要学会。

描述词矩阵 / Prompt matrix

使用|分离多个提示词,系统将会组合每个提示词用来生成图像。

例子:

a busy city street in a modern city|illustration|cinematic lighting
会生成四幅图像,分别为
a busy city street in a modern city
a busy city street in a modern city, illustration
a busy city street in a modern city, cinematic lighting
a busy city street in a modern city, illustration, cinematic lighting

生成图片:

载入描述词 / Prompts from file or textbox

可以通过此脚本创建一个列表用于顺序生成

例子

--prompt "photo of sunset" 
--prompt "photo of sunset" --negative_prompt "orange, pink, red, sea, water, lake" --width 1024 --height 768 --sampler_name "DPM++ 2M Karras" --steps 10 --batch_size 2 --cfg_scale 3 --seed 9
--prompt "photo of winter mountains" --steps 7 --sampler_name "DDIM"
--prompt "photo of winter mountains" --width 1024

输出:

以下参数受到支持:

"sd_model", "outpath_samples", "outpath_grids", "prompt_for_display", "prompt", "negative_prompt", "styles", "seed", "subseed_strength", "subseed", 
    "seed_resize_from_h", "seed_resize_from_w", "sampler_index", "sampler_name", "batch_size", "n_iter", "steps", "cfg_scale", "width", "height", 
    "restore_faces", "tiling", "do_not_save_samples", "do_not_save_grid"

XYZ 图 / XYZ plot

创建具有不同参数的多个图像网格。X 和 Y 用作行和列,而 Z 网格用作批处理维度(次数)。

使用 X 类型、Y 类型和 Z 类型字段选择应由行、列和批次使用的参数,并将这些参数以逗号分隔输入到 X/Y/Z 值字段中。

语法支持整数、浮点数和范围。例如:

生成下方的按钮

第一个按钮用于回收上次的 prompt

第二个按钮用于清除 prompt

第三个按钮用于展示额外网络结构(之后再讲)

第五个按钮用于将当前 prompt 保存为预设,可以从 styles 中调用

第四个按钮则是启用当前 styles,也就是启用预设

生成图片下方的按钮

想必大家一看便懂,不多赘述

至此,关于文生图原版的所有按钮已讲解完毕,接下来我们进入图生图

图生图 / img2img

由于图生图与文生图有很多功能和选项是一致的,所以下文只列出有差异的选项

询问 / Interrogate

webui 提供了俩种询问途径,分别是询问 CLIP 和询问 DeepBooru,这里涉及到了 CLIP 和 DeepBooru 俩个热门的模型,有必要详细讲讲。

询问 CLIP

读过第一篇的朋友已经知道,CLIP 模型是一个结合人类语言和计算机视觉的模型,它的存在意义就是为了帮助我们进行跨模态,暨从文本到图片,或者从图片到文本进行对应。

模态是指数据的存在形式,简单的来说,文本和视觉各自是一种模态。

如果你将一张图片交给 CLIP,CLIP 就会将图片判别给对应的文本,这一过程就是询问 CLIP 的本质。

例子:

首先上传图片

点击

我们就会获得

询问 DeepBooru

DeepBooru 是动漫风格的女孩图像标签估计系统(DeepDanbooru

专用于二次元,专用于二次元图片生成标签,二次元专业户

上图的对应结果:

俩种 Interrogate 的优劣

注意如果你没有使用基于 novelai 泄露的模型(该模型在训练时大量使用了 DeepBooru 的数据和对应的二次元图片),使用 DeepBooru 似乎不是明智的行为。

缩放模式 / Resize mode

四种图像处理方式

拉伸(Just resize) -- 简单的将图片缩放至指定比例,不保证原图尺寸比

裁剪(Crop and resize)-- 将图片按比例进行缩放,多余的直接裁剪掉

填充(Resize and fill)-- 将图片按比例进行缩放,缺少的部分填充

隐空间直接缩放(latent upscale)-- 其实与前面三个不同,这个是常用于图像超分辨率的快捷选项,低显存谨慎使用。

该选项直接在隐空间对图片进行缩放(拉伸),因为直接作用在隐空间所以需要比较高的去噪强度,0.7 左右比较适合,较低会造成图像模糊。(可参考上文所讲的高清修复)

去噪强度 / Denoising strength

换了一个汉化脚本,图中翻译成了重绘程度,虽然意思到了,但明显翻译没按词来

这里的去噪强度和之前我们在文生图里高清修复里的去噪强度是一致的

范围 0-1,数值越大代表离原图距离越远

采样步数 / Sampling steps

基本与文生图相同

值得注意的是,默认情况下在去噪强度较低的时候,实际采样步数会下降

具体公式为采样步数 X 去噪强度 = 实际采样步数

我认为这是十分合理的规则,如果不喜欢可以在设置里进行更改

相关设置

脚本 / Script

图生图的替代测试 / img2img alternative test

一个非常鸡肋的功能,用于 prompt 微调,可以看看你的图片如果换了某个 prompt 大概的效果是什么样

其过程是对原图进行加噪破坏然后进行减噪生成

我直接上例子吧

原图(该原图原始 prompt 为 a girl ,red eyes)

生成结果(生成的图的 prompt 的提示词被覆写为 a girl ,yellow eyes)

回送 / Loopback

也是一个相当鸡肋的功能

相当于用脚本帮你多次回环生成(上次生成的结果作为输入再次进行生成)

可以调整迭代次数和降噪系数

降噪强度的调整系数的范围为 0.9-1.1,具体作用时相当于把上次的降噪强度乘上这个调整系数值就能获得当前的降噪强度

使用上述输入得到的例子如下

效果稍差的向外绘制 / Poor man's outpainting

按照上图,我们可以简单理解为用于一张图片向外拓展像素

蒙版我认为是没啥影响的,如果选用原图作为蒙版也许会色彩更丰富,用噪声的话也许有惊喜。

例子如下:

需要注意的是,与正常生成不同,outpainting 似乎非常依赖高步数,如下图

81 steps, Euler A30 steps, Euler A10 steps, Euler A80 steps, Euler A

向外绘制第二版 / Outpainting mk2

上面 Poor man's outpainting 的改进版,翻译把我该干的事干完了,直接看图吧

使用 SD 放大 / SD upscale

非常鸡肋的功能

运行后的步骤为

可以说是非常直觉的放大方式,但是直觉要是有用还要数学干什么?

由于这种操作要较为精确计算每次分割的块,否则会出现重叠过多导致生成出鬼图,重叠过少导致图片连贯性下降。

笔者在使用过程中经常会产生如下例子:

作用前

作用后

草绘 / Sketch

局部绘制 / Inpaint

局部草绘 / Inpaint sketch

Inpaint upload

这几个属于 img2img 的二次开发,如果理解了 img2img,这些功能也没有难度

Batch

img2img 的快捷批量处理

图像增强 / Extras

翻译显然对相关领域理解不够深入,翻译成了附加功能(虽然可能理解错误的是我)

前面文生图高清修复(Hires. fix)和前面图生图放大(SD upscale)的非隐空间版

当然,放大器自然也去掉了 Latent 系列

可以发现,基本上所有的按钮前面都有讲解,所以略过

图片信息 / PNG Info

凡是 webui 或者 novelai 生成出来的图都在元文件信息位置详细介绍了这张图的生成信息

我们可以通过 webui 进行查看

值得注意的是,实际生成信息还包括了是否来自 webui 还是 novelai,只不过 webui 没有把这部分信息展现出来,建议用相关软件查看。

模型合并 / Checkpoint Merger

该区域用来合并模型,其规则都有写,如果你前面的部分都看过了,对这里应该没有理解难度。

设置 / setting

如果你看完了本篇文章和前面的俩篇文章,我可以保证setting里的选项对你来说毫无理解难度,现在就打开setting自定义你的 webui 吧~

至于训练相关和拓展相关就第四篇见面吧~

Stable Diffusion web UI整体介绍Stable Diffusion checkpoint一些疑问的解答是否选择带 ema 的版本该选择 float16 还是 float32 版本是否应该加载 vae模型文件的后缀模型文件后面 [] 内的 hash 值文生图 / txt2imgPrompt/Negative promptprompt 的语法增强 / 减弱(emphasized)渐变 / 调整作用时机(scheduled)交替(alternate)组合 / 混合(composable)断开 / 打断(BREAK)词汇的具体解析拼写错误或罕见词词汇顺序 / 数量 / 位置影响emoji 和颜文字采样方法 / Sampling methodEuler aDPM++ 2MDPM++ 2M KarrasDDIMUniPC俩个参数eta 参数sigma 参数采样步数 / Sampling steps宽 高 / Width Height正确的生成图片大小策略CFG 指数 / CFG Scale实际使用时的 CFG Scale生成 / Gennerate面部修复 / Restore faces生成无缝贴图 / Tiling高清修复 / Hires. fix图像放大器 / UpscalerLDSRR-ESRGAN 4x+R-ESRGAN 4x+ Anime6BSwinIR_4x放大步数 / Hires steps去噪强度 / Denoising strength放大倍数 / Upscale by放大至 / Resize width height to经验总结图像生成种子 / Seed附加 / Extra种子变异 / Variation seed变异强度 / Variation strength调整种子大小批量生成脚本 / Script描述词矩阵 / Prompt matrix载入描述词 / Prompts from file or textboxXYZ 图 / XYZ plot生成下方的按钮生成图片下方的按钮图生图 / img2img询问 / Interrogate询问 CLIP询问 DeepBooru俩种 Interrogate 的优劣缩放模式 / Resize mode去噪强度 / Denoising strength采样步数 / Sampling steps脚本 / Script图生图的替代测试 / img2img alternative test回送 / Loopback效果稍差的向外绘制 / Poor man's outpainting向外绘制第二版 / Outpainting mk2使用 SD 放大 / SD upscale草绘 / Sketch局部绘制 / Inpaint局部草绘 / Inpaint sketchInpaint uploadBatch图像增强 / Extras图片信息 / PNG Info模型合并 / Checkpoint Merger设置 / setting 全文完
本文由 简悦 SimpRead 转码,用以提升阅读体验,原文地址